/**
 * createStore(reducer, preloadedState, enhancer)
 * 返回 { getState, dispatch, subscribe }
 */

function createStore(reducer, preloadedState, enhancer) {
  // 约束reducer参数类型
  if(typeof reducer !== 'function') throw new TypeError('reducer必须是函数')
  // 判断enhancer参数有没有传递
  if(typeof enhancer !== 'undefined' ){  
    // 判断enhancer是不是一个函数
    if(typeof enhancer !== 'function'){
      throw new TypeError('enhancer 必须是一个函数')
    }
    return enhancer(createStore)(reducer,preloadedState)
  }
  // store 对象中存储状态
  let currentState = preloadedState
  // 存放订阅者函数
  let currentListeners = []
  // 获取状态
  function getState() {
    return currentState
  }
  // 触发action
  function dispatch(action) {
    // 判断action是否为对象
    if(!isPlainObject(action)) throw new TypeError('action必须是对象')
    // 判断对象中是否具有type属性
    if(typeof action.type === 'undefined') throw new Error('action对象中必须有type属性')
    currentState = reducer(currentState, action)
    for(let i = 0; i < currentListeners.length; i++) {
      const listener = currentListeners[i]
      listener()
    }
  }
  // 订阅状态
  function subscribe(listener) {
    currentListeners.push(listener)
  }

  return {
    getState,
    dispatch,
    subscribe
  }
}

// 判断是否为对象
function isPlainObject(obj) {
  // 排除基本类型和null
  if( typeof obj !== 'object' || obj === null) return false
  let proto = obj
  // 区分数组和对象, 原型对象对比的方式
  while(Object.getPrototypeOf(proto) !== null) {
    proto = Object.getPrototypeOf(proto)
  }
  return Object.getPrototypeOf(obj) === proto
}

// 合并处理中间件函数
function applyMiddleware(...middlers) {
  return function(createStore) {
    return function(reducer, preloadedState) {
      let store = createStore(reducer, preloadedState)
      let middlewareStore = {
        getState: store.getState,
        dispatch: store.dispatch
      }
      // 调用中间件的第一层函数，传递阉割版的store对象
      const chain = middlers.map(middleware => middleware(middlewareStore))
      // 也可以调用封装的方法来进行处理
      // const dispatch = compose(...chain)(store.dispatch)
      let dispatch = store.dispatch
      for(let i = chain.length - 1; i >=0; i--) {
        dispatch = chain[i](dispatch)
      }
      console.log(dispatch)
      // -------让dispatch可以传递一个函数来处理异步等其他操作------（不一定准确）
      function _dispatch(action) {
        if(typeof action === 'function'){
          return action(dispatch)
        }
        dispatch(action)
      }
      //  -------------------
      return {
        ...store,
        dispatch: _dispatch
      }
    }
  }
}

// 合并action,接收两个参数,所有的actions和 dispatch函数
function bindActionCreators(actionCreators, dispatch) {
  let bindActionCreators = {}
  for(let k in actionCreators) {
    (function(k){
      bindActionCreators[k] = function() {
        dispatch(actionCreators[k]())
      }
    })(k)
  }
  return bindActionCreators
}

// 合并reducer 返回一个函数, 返回的函数具有两个参数,state和action
function combineReducers(reducers){
  // 建查reducer类型，它必须是函数
  const keys = Object.keys(reducers)
  for(let i = 0; i < keys.length; i++){
    let key = keys[i]
    if(typeof reducers[key] !== 'function') throw new TypeError('reducer必须是函数')
  }
  return function(state, action) {
    // 将所有reducer最新的状态存储到一个新对象中返回
    const newReducer = {}
    for(let i = 0; i < keys.length; i++) {
      let key = keys[i]
      let reducer = reducers[key]
      // 存储状态, 执行每一个相对应的reducer函数获取最新的数据状态
      newReducer[key] = reducer(state[key], action)
    }
    return newReducer
  }
}
// 封装处理中间件传递的next函数, 最后一次调用的是dispatch函数
// function compose() {
//   const func = [...arguments]
//   return function(dispatch) {
//     for(let i = func.length - 1 ; i >= 0; i--){
//       dispatch = func[i](dispatch)
//     }
//     return dispatch
//   }
// }